home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio / Ham Radio CD-ROM (Emerald Software) (1995).ISO / misc / 9q920411 / dialer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-06  |  8.6 KB  |  389 lines

  1. /* Automatic SLIP/PPP line dialer.
  2.  *
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  *
  5.  *    Mar '91    Bill Simpson & Glenn McGregor
  6.  *        completely re-written;
  7.  *        human readable control file;
  8.  *        includes wait for string, and speed sense;
  9.  *        dials immediately when invoked.
  10.  *    May '91 Bill Simpson
  11.  *        re-ordered command line;
  12.  *        allow dial only;
  13.  *        allow inactivity timeout without ping.
  14.  *    Sep '91 Bill Simpson
  15.  *        Check known DTR & RSLD state for redial decision
  16.  *    Mar '92    Phil Karn
  17.  *        autosense modem control stuff removed
  18.  *        Largely rewritten to do demand dialing
  19.  */
  20. #include <stdio.h>
  21. #include <ctype.h>
  22. #include "global.h"
  23. #include "mbuf.h"
  24. #include "timer.h"
  25. #include "proc.h"
  26. #include "iface.h"
  27. #include "netuser.h"
  28. #include "8250.h"
  29. #include "asy.h"
  30. #include "tty.h"
  31. #include "socket.h"
  32. #include "cmdparse.h"
  33. #include "devparam.h"
  34. #include "files.h"
  35. #include "main.h"
  36. #include "trace.h"
  37. #include "commands.h"
  38.  
  39. static int redial __ARGS((struct iface *ifp,char *file));
  40. static void dropline __ARGS((void *));
  41. static void dropit(int,void *,void *);
  42.  
  43. static int dodial_control    __ARGS((int argc,char *argv[],void *p));
  44. static int dodial_send        __ARGS((int argc,char *argv[],void *p));
  45. static int dodial_speed        __ARGS((int argc,char *argv[],void *p));
  46. static int dodial_status    __ARGS((int argc,char *argv[],void *p));
  47. static int dodial_wait        __ARGS((int argc,char *argv[],void *p));
  48.  
  49. static struct cmds dial_cmds[] = {
  50.     "",        donothing,    0, 0, "",
  51.     "control",    dodial_control,    0, 2, "control up | down",
  52.     "send",        dodial_send,    0, 2,
  53.     "send \"string\" [<milliseconds>]",
  54.     "speed",    dodial_speed,    0, 2, "speed <bps>",
  55.     "status",    dodial_status, 0, 2, "status up | down",
  56.     "wait",        dodial_wait,    0, 2,
  57.     "wait <milliseconds> [ \"string\" [speed] ]",
  58.     NULLCHAR,    NULLFP,        0, 0, "Unknown command",
  59. };
  60. /* 
  61.  * dial <iface> <seconds> <raisefile> <dropfile>
  62.  * dial <iface>
  63.  * dial <iface> 0
  64.  */
  65. int
  66. dodialer(argc,argv,p)
  67. int argc;
  68. char *argv[];
  69. void *p;
  70. {
  71.     struct iface *ifp;
  72.     struct asy *ap;
  73.     int32 timeout;
  74.  
  75.     if((ifp = if_lookup(argv[1])) == NULLIF){
  76.         tprintf("Interface %s unknown\n",argv[1]);
  77.         return 1;
  78.     }
  79.     if(ifp->dev >= ASY_MAX || Asy[ifp->dev].iface != ifp){
  80.         tprintf("Interface %s not asy port\n",argv[1]);
  81.         return 1;
  82.     }
  83.     ap = &Asy[ifp->dev];
  84.     if(argc < 3){
  85.         tprintf("%s: %s",ifp->name,(ap->msr & MSR_RLSD) ? "UP":"DOWN");
  86.         tprintf(", idle timer %ld/%ld",read_timer(&ap->idle)/1000L,
  87.           dur_timer(&ap->idle)/1000L);
  88.         if(ap->actfile != NULLCHAR)
  89.             tprintf(", up script: %s",ap->actfile);
  90.         if(ap->dropfile != NULLCHAR)
  91.             tprintf(", down script: %s\n",ap->dropfile);
  92.         else
  93.             tprintf("\n");
  94.  
  95.         tprintf("Calls originated %ld, carrier up transitions %ld\n",
  96.             ap->originates,ap->answers);
  97.         tprintf("Calls timed out %ld, carrier down transitions %ld\n",
  98.             ap->localdrops,ap->remdrops);
  99.         return 0;
  100.     }
  101.     timeout = atol(argv[2]) * 1000L;
  102.     if(timeout != 0 && argc < 5){
  103.         tprintf("Usage: dial <iface> <timeout> <raisefile> <dropfile>\n");
  104.         tprintf("       dial <iface> 0\n");
  105.         return 1;
  106.     }
  107.     if(!ap->rlsd){
  108.         tprintf("Must set 'r' flag at attach time\n");
  109.         return 1;
  110.     }
  111.     stop_timer(&ap->idle);
  112.     set_timer(&ap->idle,timeout);
  113.     ap->idle.func = dropline;
  114.     ap->idle.arg = ifp;
  115.     if(ap->actfile != NULLCHAR){
  116.         free(ap->actfile);
  117.         ap->actfile = NULLCHAR;
  118.     }
  119.     if(ap->dropfile != NULLCHAR){
  120.         free(ap->dropfile);
  121.         ap->dropfile = NULLCHAR;
  122.     }
  123.     if(timeout != 0){
  124.         ap->actfile = strdup(argv[3]);
  125.         ap->dropfile = strdup(argv[4]);
  126.         start_timer(&ap->idle);
  127.     }
  128.     return 0;
  129. }
  130. void
  131. dialer_kick(asyp)
  132. struct asy *asyp;
  133. {
  134.     stop_timer(&asyp->idle);
  135.     while(asyp->rlsd && (asyp->msr & MSR_RLSD) == 0
  136.      && asyp->actfile != NULLCHAR){
  137.         /* Line down, need to redial it */
  138.         asyp->originates++;
  139.         redial(asyp->iface,asyp->actfile);
  140.     }
  141. }
  142.  
  143. /* Called when idle line timer expires -- executes script to drop line */
  144. static void
  145. dropline(p)
  146. void *p;
  147. {
  148.     /* Fork this off to prevent wedging the timer task */
  149.     newproc("dropit",512,dropit,0,p,NULL,0);
  150. }
  151.  
  152. static void
  153. dropit(i,p,u)
  154. int i;
  155. void *p;
  156. void *u;
  157. {
  158.     struct iface *ifp = p;
  159.     struct asy *ap;
  160.  
  161.     ap = &Asy[ifp->dev];
  162.     if(ap->msr & MSR_RLSD){
  163.         ap->localdrops++;
  164.         redial(ifp,ap->dropfile);    /* Drop only if still up */
  165.     }
  166. }
  167.  
  168. /* execute dialer commands
  169.  * returns: -1 fatal error, 0 OK, 1 try again
  170.  */
  171. static int
  172. redial(ifp,file)
  173. struct iface *ifp;
  174. char *file;
  175. {
  176.     char *inbuf, *intmp;
  177.     FILE *fp;
  178.     int (*rawsave) __ARGS((struct iface *,struct mbuf *));
  179.     int result = 0;
  180.     int save_input = Curproc->input;
  181.     int save_output = Curproc->output;
  182.  
  183.     if((fp = fopen(file,READ_TEXT)) == NULLFILE){
  184.         if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  185.             fprintf(ifp->trfp,"redial: can't read %s\n",file);
  186.         return -1;
  187.     }
  188.     /* Save output handler and temporarily redirect output to null */
  189.     if(ifp->raw == bitbucket){
  190.         if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  191.             fprintf(ifp->trfp,"redial: tip or dialer already active on %s\n",ifp->name);
  192.  
  193.         return -1;
  194.     }
  195.  
  196.     if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  197.         fprintf(ifp->trfp,"Dialing on %s\n\n",ifp->name);
  198.  
  199.     /* Save output handler and temporarily redirect output to null */
  200.     rawsave = ifp->raw;
  201.     ifp->raw = bitbucket;
  202.  
  203.     /* Suspend the packet input driver. Note that the transmit driver
  204.      * is left running since we use it to send buffers to the line.
  205.      */
  206.     suspend(ifp->rxproc);
  207.  
  208.     inbuf = mallocw(BUFSIZ);
  209.     intmp = mallocw(BUFSIZ);
  210.     while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  211.         strcpy(intmp,inbuf);
  212.         rip(intmp);
  213.         log(-1,"%s dialer: %s",ifp->name,intmp);
  214.         if((result = cmdparse(dial_cmds,inbuf,ifp)) != 0){
  215.             if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  216.                 fprintf(ifp->trfp,"input line: %s",intmp);
  217.             break;
  218.         }
  219.     }
  220.     free(inbuf);
  221.     free(intmp);
  222.     fclose(fp);
  223.  
  224.     if(result == 0){
  225.         ifp->lastsent = ifp->lastrecv = secclock();
  226.     }
  227.     ifp->raw = rawsave;
  228.     resume(ifp->rxproc);
  229.     if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  230.         fprintf(ifp->trfp,"\nDial %s complete\n",ifp->name);
  231.  
  232.     Curproc->input = save_input;
  233.     Curproc->output = save_output;
  234.     return result;
  235. }
  236.  
  237.  
  238. static int
  239. dodial_control(argc,argv,p)
  240. int argc;
  241. char *argv[];
  242. void *p;
  243. {
  244.     struct iface *ifp = p;
  245.     int param;
  246.  
  247.     if ( ifp->ioctl == NULL )
  248.         return -1;
  249.  
  250.     if ( (param = devparam( argv[1] )) == -1 )
  251.         return -1;
  252.  
  253.     (*ifp->ioctl)( ifp, param, TRUE, atol( argv[2] ) );
  254.     return 0;
  255. }
  256.  
  257.  
  258. static int
  259. dodial_send(argc,argv,p)
  260. int argc;
  261. char *argv[];
  262. void *p;
  263. {
  264.     struct iface *ifp = p;
  265.     struct mbuf *bp;
  266.  
  267.     if(argc > 2){
  268.         /* Send characters with inter-character delay
  269.          * (for dealing with prehistoric Micom switches that
  270.          * can't take back-to-back characters...yes, they
  271.          * still exist.)
  272.          */
  273.         char *cp;
  274.         int32 cdelay = atol(argv[2]);
  275.  
  276.         for(cp = argv[1];*cp != '\0';cp++){
  277.             asy_write(ifp->dev,cp,1);
  278.             pause(cdelay);
  279.         }
  280.     } else {
  281.         if (ifp->trace & IF_TRACE_RAW)
  282.             raw_dump( ifp, IF_TRACE_OUT, bp );
  283.         asy_write(ifp->dev,argv[1],strlen(argv[1]));
  284.     }
  285.     return 0;
  286. }
  287.  
  288.  
  289. static int
  290. dodial_speed(argc,argv,p)
  291. int argc;
  292. char *argv[];
  293. void *p;
  294. {
  295.     struct iface *ifp = p;
  296.  
  297.     if ( argc < 2 ) {
  298.         if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  299.             fprintf(ifp->trfp,"current speed = %u bps\n", Asy[ifp->dev].speed);
  300.         return 0;
  301.     }
  302.     return asy_speed( ifp->dev, (int16)atol( argv[1] ) );
  303. }
  304.  
  305.  
  306. static int
  307. dodial_status(argc,argv,p)
  308. int argc;
  309. char *argv[];
  310. void *p;
  311. {
  312.     struct iface *ifp = p;
  313.     int param;
  314.  
  315.     if ( ifp->iostatus == NULL )
  316.         return -1;
  317.  
  318.     if ( (param = devparam( argv[1] )) == -1 )
  319.         return -1;
  320.  
  321.     (*ifp->iostatus)( ifp, param, atol( argv[2] ) );
  322.     return 0;
  323. }
  324.  
  325.  
  326. static int
  327. dodial_wait(argc,argv,p)
  328. int argc;
  329. char *argv[];
  330. void *p;
  331. {
  332.     struct iface *ifp = p;
  333.     register int c = -1;
  334.  
  335.     alarm(atol(argv[1]));
  336.  
  337.     if(argc == 2){
  338.         while((c = get_asy(ifp->dev)) != -1 ){
  339.             c &= 0x7f;
  340.             if(ifp->trace & IF_TRACE_IN){
  341.                 fputc(c,ifp->trfp);
  342.                 fflush(ifp->trfp);
  343.             }
  344.         }
  345.         alarm(0L);
  346.         return 0;
  347.     } else {
  348.         register char *cp = argv[2];
  349.  
  350.         while(*cp != '\0' && (c = get_asy(ifp->dev)) != -1){
  351.             c &= 0x7f;
  352.             if(ifp->trace & IF_TRACE_IN){
  353.                 fputc(c,ifp->trfp);
  354.                 fflush(ifp->trfp);
  355.             }
  356.             if(*cp++ != c){
  357.                 cp = argv[2];
  358.             }
  359.         }
  360.  
  361.         if(argc > 3){
  362.             if(stricmp( argv[3], "speed") == 0){
  363.                 int16 speed = 0;
  364.  
  365.                 while((c = get_asy(ifp->dev)) != -1){
  366.                     c &= 0x7f;
  367.                     if(ifp->trace & IF_TRACE_IN){
  368.                         fputc(c,ifp->trfp);
  369.                         fflush(ifp->trfp);
  370.                     }
  371.                     if(isdigit(c)){
  372.                         speed *= 10;
  373.                         speed += c - '0';
  374.                     } else {
  375.                         alarm(0L);
  376.                         return asy_speed( ifp->dev, speed );
  377.                     }
  378.                 }
  379.             } else {
  380.                 return -1;
  381.             }
  382.         }
  383.     }
  384.     alarm(0L);
  385.     return (c == -1);
  386. }
  387.  
  388.  
  389.